package com.cloudinnov.utils;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;

import com.cloudinnov.logic.CarDetectorLogic;
import com.cloudinnov.model.CarDetectorData;
import com.cloudinnov.utils.support.spring.SpringUtils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * @author chengning
 * @date 2016年12月17日下午6:39:36
 * @email ningcheng@cloudinnov.com
 * @remark
 * @version
 */
public class CarDetectorServer {
	static final Logger LOG = Logger.getLogger(CarDetectorServer.class);
	public static final String TOTAL_CAR = "total:car";
	public static final String CAL_NAME = "car:deviceId:";
	public static final String CAL_VALUE = ":value";
	private static final int RECENT_LIST_COUNT = 10000;
	public static final String SPLITTER_LEVEL0 = ",";
	private CarDetectorLogic carDetectorLogic = SpringUtils.getBean("carDetectorLogic");
	private JedisPool jedisPool = SpringUtils.getBean("jedisPool");
	private int port;

	public CarDetectorServer(int port) {
		this.port = port;
	}
	/**
	 * 初始化车检仪Tcp接收程序
	 * @Title: initTcpRevice
	 * @Description: TODO
	 * @return: void
	 * @throws IOException
	 */
	public void initTcpRevice() {
		new Thread() {
			public void run() {
				System.out.println("Init CarDetectorServer Tcp Port " + port + " Success!");
				ServerSocket server;
				try {
					server = new ServerSocket(port);
					while (true) {
						Socket socket = server.accept();
						System.out.println("ip: " + socket.getInetAddress().getHostAddress() + " enter, time: "
								+ System.currentTimeMillis());
						new SocketThread(socket).start();
					}
				} catch (IOException e) {
					LOG.error("initTcpRevice is error, e:  {}", e);
				}
			};
		}.start();
	}

	class SocketThread extends Thread {
		private Socket socket;

		public SocketThread(Socket socket) throws IOException {
			this.socket = socket;
		}
		@Override
		public void run() {
			CarDetectorData model = null;
			String keyRealtime, totalName, value;
			while (true) {
				Jedis redis = null;
				try {
					redis = jedisPool.getResource();
					InputStream in = socket.getInputStream();
					int count = 0;
					while (count == 0) {
						count = in.available();
					}
					byte[] data = new byte[count];
					in.read(data, 0, data.length);
					if (data.length > 44) {
						model = new CarDetectorData();
					}
					String values = hex(data);
					System.out.println("原始数据：" + values);
					String newData = bytesToHexString(data);
					System.out.println("车检仪器数据：  " + newData);
					int lineId = 1;
					// 得到设备唯一ID
					model.setDeviceId(newData.substring(8, 24));
					// 获取时间和日期
					model.setSummaryTime(newData.substring(40, 54));
					// 获取周期
					model.setPeriod(Integer.parseInt(newData.substring(54, 58), 16));
					// 车辆总数
					model.setCarTotal(Long.parseLong(newData.substring(58, 62), 16));
					// 车道数
					model.setLaneTotal(Integer.parseInt(newData.substring(62, 64), 16));
					
					int firstLaneData = Integer.parseInt(newData.substring(68, 72),16);
					int secondLaneData=Integer.parseInt(newData.substring(92,96),16);
					int thirdLaneData=Integer.parseInt(newData.substring(116,120),16);
					int forthLaneData=Integer.parseInt(newData.substring(140,144),16);
					int fifthLaneData=Integer.parseInt(newData.substring(164,168),16);
					int sixthLaneData=Integer.parseInt(newData.substring(188,192),16);
					
					int beyondLaneData= firstLaneData+secondLaneData+thirdLaneData;
					int behindLaneData=forthLaneData+fifthLaneData+sixthLaneData;
					
					
					model.setUtcTime(new Date());
					model.setTimeMillis(System.currentTimeMillis());
					// 车道数据共12个字节和2字节crc校验包括：
					String lineData = newData.substring(64, newData.length() - 4);
					keyRealtime = CAL_NAME + model.getDeviceId() + CAL_VALUE;
					totalName = TOTAL_CAR + CAL_VALUE;
					value = model.getCarTotal() + SPLITTER_LEVEL0 + model.getTimeMillis()+SPLITTER_LEVEL0+beyondLaneData+SPLITTER_LEVEL0+behindLaneData;
					redis.lpush(keyRealtime, value);// 单个车检仪器只保存最新的3000条数据
					redis.ltrim(keyRealtime, 0L, RECENT_LIST_COUNT);
					redis.set(totalName, value);// 总数只保留最新的一条
					List<CarDetectorData.CarDetectorDataChilren> lineDatas = new ArrayList<>();
					System.out.println("lineData.length：　" + lineData.length());
					System.out.println("lineData" + lineData);
					for (int j = 0; j < lineData.length(); j += 28) {
						if (lineData.substring(j, j + 5).indexOf("ff00") != -1) {
							break;
						}
						CarDetectorData.CarDetectorDataChilren laneData = new CarDetectorData().new CarDetectorDataChilren();
						laneData.setLineAvgVelocuty(Integer.parseInt(lineData.substring(j, j + 2), 16));
						laneData.setLineOccRate(Integer.parseInt(lineData.substring(j + 2, j + 4), 16));
						laneData.setLineFlow(Integer.parseInt(lineData.substring(j + 4, j + 8), 16));
						laneData.setLineOneClassflow(Integer.parseInt(lineData.substring(j + 8, j + 12), 16));
						laneData.setLineTwoClassflow(Integer.parseInt(lineData.substring(j + 12, j + 16), 16));
						laneData.setLineThreeClassflow(Integer.parseInt(lineData.substring(j + 16, j + 20), 16));
						laneData.setLineFourClassflow(Integer.parseInt(lineData.substring(j + 20, j + 24), 16));
						laneData.setLineId(lineId);
						lineDatas.add(laneData);
						lineId++;
					}
					model.setData(lineDatas);
					carDetectorLogic.saveRealTimeDataToMongoDB(model);
				} catch (Exception e) {
					LOG.error("send Data To carDetectorQueue Is Bad, error: ", e);
				} finally {
					jedisPool.returnResource(redis);
				}
			}
		}
	}

	/**
	 * byte数组转换成16进制字符串
	 * @param src
	 * @return
	 */
	public static String bytesToHexString(byte[] src) {
		StringBuilder stringBuilder = new StringBuilder();
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}
	/**
	 * byte数组转换成16进制字符数组
	 * @param src
	 * @return
	 */
	public static String[] bytesToHexStrings(byte[] src) {
		if (src == null || src.length <= 0) {
			return null;
		}
		String[] str = new String[src.length];
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				str[i] = "0";
			}
			str[i] = hv;
		}
		return str;
	}
	
	private static String hex(byte[] bytes){
	    char[] alpha = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
	    StringBuilder strBuilder = new StringBuilder(bytes.length * 2);
	    for(byte b : bytes){
	        strBuilder.append(alpha[b >>> 4 & 0xf]).append(alpha[b & 0xf]);
	    }
	    return strBuilder.toString();
	}
}
